#include "logutil.h"
#include <QDir>
#include <QTextStream>
#include <QDebug>

// 静态成员初始化
LogUtil* LogUtil::m_instance = nullptr;
QMutex LogUtil::m_instanceMutex;

LogUtil::LogUtil(QObject* parent)
    : QObject(parent)
{
    // 初始化默认日志路径
    m_logPath = m_defaultDir + m_defaultFileName;
    // 自动创建日志文件（若失败，后续日志会输出到控制台兜底）
    if (!initLogFile()) {
        qCritical() << "[LogUtil] 日志文件初始化失败，将使用控制台输出";
    }
}

LogUtil* LogUtil::getInstance(QObject* parent)
{
    if (!m_instance) {
        QMutexLocker locker(&m_instanceMutex);
        if (!m_instance) {
            m_instance = new LogUtil(parent);
        }
    }
    return m_instance;
}

LogUtil::~LogUtil()
{
    if (m_logFile.isOpen()) {
        m_logFile.close();
    }
    m_instance = nullptr;
}

void LogUtil::setLogPath(const QString& path)
{
    QMutexLocker locker(&m_writeMutex);
    if (path.isEmpty()) return;

    // 关闭现有文件，切换到新路径
    if (m_logFile.isOpen()) {
        m_logFile.close();
    }
    m_logPath = path;
    initLogFile();
    LOG_INFO("LogUtil", QString("日志路径已切换至：%1").arg(m_logPath));
}

void LogUtil::debug(const QString& module, const QString& message)
{
    writeLog(LogLevel::Debug, module, message);
}

void LogUtil::info(const QString& module, const QString& message)
{
    writeLog(LogLevel::Info, module, message);
}

void LogUtil::warning(const QString& module, const QString& message)
{
    writeLog(LogLevel::Warning, module, message);
}

void LogUtil::error(const QString& module, const QString& message)
{
    writeLog(LogLevel::Error, module, message);
}

void LogUtil::critical(const QString& module, const QString& message)
{
    writeLog(LogLevel::Critical, module, message);
}

// 核心：统一日志写入（线程安全）
void LogUtil::writeLog(LogLevel level, const QString& module, const QString& message)
{
    QMutexLocker locker(&m_writeMutex);  // 确保多线程下文件写入安全

    // 格式化日志内容
    QString logContent = formatLog(level, module, message);

    // 优先写入文件，失败则输出到控制台
    if (m_logFile.isOpen()) {
        QTextStream out(&m_logFile);
        out.setEncoding(QStringConverter::Utf8);
        out << logContent << "\n";
        out.flush();  // 强制刷新，确保日志实时写入
    } else {
        // 控制台兜底输出（区分级别）
        switch (level) {
            case LogLevel::Debug:    qDebug() << logContent; break;
            case LogLevel::Info:     qInfo() << logContent; break;
            case LogLevel::Warning:  qWarning() << logContent; break;
            case LogLevel::Error:    qCritical() << logContent; break;
            case LogLevel::Critical: qFatal() << logContent; break;
        }
    }
}

// 格式化日志：[2024-10-20 15:30:00][Info][InputTextEdit] 初始化完成
QString LogUtil::formatLog(LogLevel level, const QString& module, const QString& message)
{
    // 时间格式：年-月-日 时:分:秒
    QString timeStr = QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss");

    // 日志级别文本（中文标识，便于阅读）
    QString levelStr;
    switch (level) {
        case LogLevel::Debug:    levelStr = "Debug";    break;
        case LogLevel::Info:     levelStr = "Info";     break;
        case LogLevel::Warning:  levelStr = "Warning";  break;
        case LogLevel::Error:    levelStr = "Error";    break;
        case LogLevel::Critical: levelStr = "Critical"; break;
    }

    // 拼接日志内容（固定格式，便于后续日志分析工具解析）
    return QString("[%1][%2][%3] %4").arg(timeStr, levelStr, module, message);
}

// 初始化日志文件：创建目录+打开文件（追加模式）
bool LogUtil::initLogFile()
{
    QDir logDir(m_defaultDir);
    // 若目录不存在，创建目录（包括父目录）
    if (!logDir.exists() && !logDir.mkpath(".")) {
        qCritical() << "[LogUtil] 无法创建日志目录：" << m_defaultDir;
        return false;
    }

    // 以追加模式打开文件（不存在则自动创建）
    m_logFile.setFileName(m_logPath);
    if (!m_logFile.open(QIODevice::Append | QIODevice::Text)) {
        qCritical() << "[LogUtil] 无法打开日志文件：" << m_logFile.errorString();
        return false;
    }

    // 写入启动日志（标记新会话）
    QString startMsg = QString("日志会话启动，日志路径：%1").arg(m_logPath);
    writeLog(LogLevel::Info, "LogUtil", startMsg);
    return true;
}
